package com.ipan.kits.io;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import com.ipan.kits.base.ExceptionUtil;
import com.ipan.kits.text.Charsets;

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.EncryptionMethod;

/**
 * zip加密解密
 * 
 * 参考 https://github.com/srikanth-lingala/zip4j
 * 
 * @author iPan
 * @date 2022-05-10
 */
public class Zip4jUtil {
	
	/**
	 * 压缩文件
	 * 
	 * @param desZipPath 目标文件路径
	 * @param password 密码
	 * @param srcPaths 源文件路径
	 */
	public static void zipFiles(String desZipPath, String password, String ...srcPaths) {
		if (srcPaths == null || srcPaths.length < 1) {
			return ;
		}
		try {
			File desZipFile = new File(desZipPath);
			if (desZipFile.exists() && desZipFile.isFile()) FileUtil.deleteFile(desZipFile); // 实际上，当存在的时候，并不完全覆盖源文件；所以，先删除；
			String parentPath = FileUtil.normalizeParentPath(desZipPath);
			FileUtil.makesureDirExists(parentPath);
			ZipFile destFile = null;
			ZipParameters parameters = new ZipParameters();
			if (StringUtils.isEmpty(password)) {
		        destFile = new ZipFile(desZipPath);
			} else {
				destFile = new ZipFile(desZipPath, password.toCharArray());
				parameters.setEncryptFiles(true);
		        parameters.setEncryptionMethod(EncryptionMethod.AES);
		        parameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
			}
	        List<File> files = new ArrayList<File>();
	        for (String item : srcPaths) {
	        	File f = new File(item);
	        	files.add(f);
	        }
	        destFile.addFiles(files, parameters);
		} catch(Exception e) {
			throw ExceptionUtil.wrapRuntime(e);
		}
	}
	/**
	 * 压缩目录
	 * 
	 * 支持递归压缩目录下的文件及目录
	 * 
	 * @param desZipPath 目标文件路径
	 * @param password 密码
	 * @param srcPaths 源目录
	 */
	public static void zipFolder(String desZipPath, String password, String srcDir) {
		if (srcDir == null || srcDir.length() < 1) {
			return ;
		}
		try {
			File desZipFile = new File(desZipPath);
			if (desZipFile.exists() && desZipFile.isFile()) FileUtil.deleteFile(desZipFile); // 实际上，当存在的时候，并不完全覆盖源文件；所以，先删除；
			String parentPath = FileUtil.normalizeParentPath(desZipPath);
			FileUtil.makesureDirExists(parentPath);
			ZipFile destFile = null;
			ZipParameters parameters = new ZipParameters();
			if (StringUtils.isEmpty(password)) {
		        destFile = new ZipFile(desZipPath);
			} else {
				destFile = new ZipFile(desZipPath, password.toCharArray());
				parameters.setEncryptFiles(true);
		        parameters.setEncryptionMethod(EncryptionMethod.AES);
		        parameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
			}
	        destFile.addFolder(new File(srcDir), parameters);
		} catch(Exception e) {
			throw ExceptionUtil.wrapRuntime(e);
		}
	}
	
	/**
	 * 解压文件
	 * 
	 * @param desPath 目标路径
	 * @param srcPath 源文件路径
	 */
	public static void unzip(String desPath, String srcPath) {
		unzip(desPath, null, srcPath);
	}
	/**
	 * 解压文件
	 * 
	 * @param desPath 目标路径
	 * @param password 密码
	 * @param srcPath 源文件路径
	 */
	public static void unzip(String desPath, String password, String srcPath) {
		try {
			char[] passChar = (StringUtils.isEmpty(password)) ? null : password.toCharArray();
			ZipFile srcFile = new ZipFile(srcPath, passChar);   
			srcFile.setCharset(Charsets.UTF_8);   
			srcFile.extractAll(desPath);
		} catch (IllegalArgumentException e) {
			throw ExceptionUtil.wrapRuntime(e);
		} catch (ZipException e) {
			throw ExceptionUtil.wrapRuntime(e);
		}
	}

}
